package com.yuju.guest.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wxpay.common.WxConstant;
import com.wxpay.demo.WxPayDto;
import com.wxpay.utils.GetWxOrderno;
import com.wxpay.utils.RequestHandler;
import com.wxpay.utils.Sha1Util;
import com.wxpay.utils.TenpayUtil;
import com.yuju.cache.RedisCache;
import com.yuju.common.Result;
import com.yuju.constant.CacheKey;
import com.yuju.constant.Constant;
import com.yuju.enums.ReturnStatusEnum;
import com.yuju.enums.WxPayForScanReturnCodeEnum;
import com.yuju.exception.BusinessException;
import com.yuju.guest.service.WxPayService;
import com.yuju.order.enums.ReserveReturnCodeEnum;
import com.yuju.order.enums.ReserveStatusEnum;
import com.yuju.order.model.ReserveModel;
import com.yuju.order.service.IReserverService;
import com.yuju.order.service.IRoomOrderService;
import com.yuju.util.ConfigUtil;

@Service("wxPayService")
public class WxPayServiceImpl implements WxPayService {
	private RedisCache<String, String> cache = RedisCache.getInstance();
	
	@Autowired
	private IReserverService reserveService;
	
	@Autowired
	private IRoomOrderService roomOrderService;
	@Override
	public String getPayPackage(String orderNo, String openId, String ip) {
		// 查询订单
		ReserveModel tradeReserve = new ReserveModel();
		tradeReserve.setReserveNo(orderNo);
		ReserveModel find  = reserveService.find(tradeReserve);
		if(find == null){
			throw new BusinessException(ReserveReturnCodeEnum.RESERVE_QUERY_FAILURE.getCode()
					, ReserveReturnCodeEnum.RESERVE_QUERY_FAILURE.getDesc());
		}
		if(find.getReserveStatus() != ReserveStatusEnum.WAITFORPAY.getValue()){
			throw new BusinessException(ReserveReturnCodeEnum.RESERVE_ROOM_HAVING_PAY.getCode()
					, ReserveReturnCodeEnum.RESERVE_ROOM_HAVING_PAY.getDesc()+find.getReserveStatusName());
		}
		String totalFee = String.valueOf(find.getUnpaidMoney());
		String billTitle = "会员订单";
		// 微信支付jsApi
		WxPayDto tpWxPay = new WxPayDto();
		tpWxPay.setOpenId(openId);
		tpWxPay.setBody(billTitle);
		tpWxPay.setOrderId(orderNo);
		tpWxPay.setSpbillCreateIp(ip);
		tpWxPay.setTotalFee(totalFee);// 默认直接接应付金额
		tpWxPay.setAttach("");
	
		String tradeType = "JSAPI";
		
		String payPackage = getPackage(tpWxPay, tradeType, find.getGroupId());
		System.out.println(payPackage);
		return payPackage;
	}
	public String getPackage(WxPayDto tpWxPayDto, String tradeType, String groupId) {
		String appId = cache.get(groupId + Constant.APP_ID + CacheKey.KEY_GRP_PARAM);
		String appSecret = cache.get(groupId + Constant.APP_SECRET + CacheKey.KEY_GRP_PARAM);
		String mchId = cache.get(groupId + Constant.MCH_ID + CacheKey.KEY_GRP_PARAM);
		String mchKey = cache.get(groupId + Constant.MCH_KEY + CacheKey.KEY_GRP_PARAM);
		String notifyUrl = cache.get(groupId + Constant.WX_NOTIFY_URL + CacheKey.KEY_GRP_PARAM);
				
		String openId = tpWxPayDto.getOpenId();
		// 1 参数
		// 订单号
		String orderId = tpWxPayDto.getOrderId();
		// 附加数据 原样返回
		String attach = tpWxPayDto.getAttach();
		// 门店ID
		String storeId = tpWxPayDto.getStoreId();
		// 总金额以分为单位，不带小数点
		String totalFee = getMoney(tpWxPayDto.getTotalFee());
		System.out.println("totalFee" + totalFee);

		// 订单生成的机器 IP
		String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
		// 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
		String notify_url = notifyUrl;
		String trade_type = tradeType; //"JSAPI";

		// ---必须参数
		// 商户号
		String mch_id = mchId;
		// 随机字符串
		String nonce_str = getNonceStr();

		// 商品描述根据情况修改
		String body = tpWxPayDto.getBody();

		String detail = tpWxPayDto.getDetail();

		// 商户订单号
		String out_trade_no = orderId;

		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appId);
		packageParams.put("mch_id", mch_id);
		packageParams.put("nonce_str", nonce_str);
		packageParams.put("body", body);
		// packageParams.put("detail", detail);
		packageParams.put("attach", attach);
		packageParams.put("out_trade_no", out_trade_no);

		// 这里写的金额为1 分到时修改
		packageParams.put("total_fee", totalFee);// totalFee
		packageParams.put("spbill_create_ip", spbill_create_ip);
		packageParams.put("notify_url", notify_url);

		packageParams.put("trade_type", trade_type);
		packageParams.put("openid", openId);
//		packageParams.put("key", constant.getPartnerkey());

		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(appId, appSecret, mchKey);

		String sign = reqHandler.createSign(packageParams);
		// + "<detail>"+ detail + "</detail>"
		String xml = "<xml>" + "<appid>" + appId + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
				+ "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>" + "<body><![CDATA[" + body
				+ "]]></body>" + "<out_trade_no>" + out_trade_no + "</out_trade_no>" + "<attach>" + attach + "</attach>"
				+ "<total_fee>" + totalFee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
				+ "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>" + trade_type
				+ "</trade_type><openid>" + openId + "</openid></xml>";
		System.out.println("==========================");
		System.out.println(xml);
		String prepay_id = "";
		String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		System.out.println("===========================" + prepay_id);
		prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
		System.out.println("获取到的预支付ID：" + prepay_id);

		// 获取prepay_id后，拼接最后请求支付所需要的package

		SortedMap<String, String> finalpackage = new TreeMap<String, String>();
		String timestamp = Sha1Util.getTimeStamp();
		String packages = "prepay_id=" + prepay_id;
		finalpackage.put("appId", appId);
		finalpackage.put("timeStamp", timestamp);
		finalpackage.put("nonceStr", nonce_str);
		finalpackage.put("package", packages);
		finalpackage.put("signType", "MD5");
		// 要签名
		String finalsign = reqHandler.createSign(finalpackage);

		String finaPackage = "{\"appId\":\"" + appId + "\",\"timeStamp\":\"" + timestamp
				+ "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\"" + packages + "\",\"signType\" : \"MD5"
				+ "\",\"paySign\":\"" + finalsign + "\"}";

		System.out.println("V3 jsApi package:" + finaPackage);
		return finaPackage;
	}

	/**
	 * 元转换成分
	 * 
	 * @param money
	 * @return
	 */
	public String getMoney(String amount) {
		if (amount == null) {
			return "";
		}
		// 金额转化为分为单位
		String currency = amount.replaceAll("\\$|\\￥|\\,", ""); // 处理包含, ￥
																// 或者$的金额
		int index = currency.indexOf(".");
		int length = currency.length();
		Long amLong = 0l;
		if (index == -1) {
			amLong = Long.valueOf(currency + "00");
		} else if (length - index >= 3) {
			amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
		} else if (length - index == 2) {
			amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
		} else {
			amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
		}
		return amLong.toString();
	}
	
	/**
	 * 获取随机字符串
	 * 
	 * @return
	 */
	public String getNonceStr() {
		// 随机数
		String currTime = TenpayUtil.getCurrTime();
		// 8位日期
		String strTime = currTime.substring(8, currTime.length());
		// 四位随机数
		String strRandom = TenpayUtil.buildRandom(4) + "";
		// 10位序列号,可以自行调整。
		return strTime + strRandom;
	}
	/**
	 * 
	 * 功能: <br/>
	 * 
	 * @Date ：2018年1月17日 下午4:59:55<br/>
	 * 重写：sunyl <br/>
	 * @param out_trade_no 订单号
	 * @param auth_code 授权码
	 * @param spbill_create_ip 终端ip
	 * @return <br/>
	 * @throws Exception 
	 * @see com.yuju.guest.service.WxPayService#wxPayForScanCode(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result microPay(BigDecimal money,String out_trade_no, String auth_code, String spbill_create_ip,String flag) throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid", appid);
        data.put("auth_code", auth_code);
        data.put("body", "门店扫码");
        data.put("mch_id",mch_id);
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
		String totalFee = getMoney(money.toString());
		// 这里写的金额为1 分到时修改
		data.put("spbill_create_ip", spbill_create_ip);
        data.put("total_fee", totalFee);// totalFee
        
        RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/pay/micropay";
		 String  xml = "<xml>"+
			   "<appid>"+appid+"</appid>"+
			   "<auth_code>"+auth_code+"</auth_code>"+
			   "<body>门店扫码</body>"+
			   "<mch_id>"+mch_id+"</mch_id>"+
			   "<nonce_str>"+nonce_str+"</nonce_str>"+
			   "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
			   "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
			   "<total_fee>"+totalFee+"</total_fee>"+
			   "<sign>"+sign+"</sign>"+
			"</xml>";
		 return  handelPayResult(GetWxOrderno.getHttpMap(url, xml),out_trade_no,flag);
	}
	/**
	 * 服务商
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年2月6日 上午9:53:20 <br/>
	 */
	@Override
	public Result microPayForService(String groupId,BigDecimal money,String out_trade_no, String auth_code, String spbill_create_ip,String flag) throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
	/*	String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);*/
		String mch_id = cache.get(groupId + Constant.MCH_ID + CacheKey.KEY_GRP_PARAM);
		String appid = cache.get(groupId + Constant.APP_ID + CacheKey.KEY_GRP_PARAM);
		String sub_mch_id = "1498287672";
		String nonce_str = getNonceStr();
		data.put("appid", appid);
		data.put("auth_code", auth_code);
		data.put("body", "门店扫码");
		data.put("mch_id","1497953662");
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		String totalFee = getMoney(money.toString());
		// 这里写的金额为1 分到时修改
		data.put("spbill_create_ip", spbill_create_ip);
		data.put("sub_mch_id", sub_mch_id);
		data.put("total_fee", totalFee);// totalFee
		System.out.println(data.toString());
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/pay/micropay";
		String xml = "<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<auth_code>"+auth_code+"</auth_code>"
					   +"<body>门店扫码</body>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"
					   +"<total_fee>"+totalFee+"</total_fee>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		return  handelPayResultForService(GetWxOrderno.getHttpMap(url, xml),out_trade_no,flag);
	}
	/**
	 * 处理支付返回结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 下午6:04:47 <br/>
	 */
	private Result handelPayResult(Map resultMap,String orderNo,String flag) throws Exception{
		Result result  = new Result();
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		String result_code = resultMap.get("result_code").toString();
		Object err_code = resultMap.get("err_code");
		long times = 0;
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
			}else{
				if(err_code.toString().equals("USERPAYING")){
						result = handelQueryResult(orderNo, flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(err_code_des);
				}
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 处理支付返回结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 下午6:04:47 <br/>
	 */
	private Result handelPayResultForService(Map resultMap,String orderNo,String flag) throws Exception{
		Result result  = new Result();
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		String result_code = resultMap.get("result_code").toString();
		Object err_code = resultMap.get("err_code");
		long times = 0;
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
			}else{
				if(err_code.toString().equals("USERPAYING")){
					result = handelQueryResultForService(orderNo, flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(err_code_des);
				}
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 查询并处理支付结果
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年1月18日 下午6:09:53 <br/>
	 */
	private Result handelQueryResult(String orderNo,String flag,long times) throws Exception{
		Thread.sleep(5000);//停顿5秒，继续查询
		times = times + 5000;
		if(times >= 30000){
			throw new BusinessException(WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getCode()
					,WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getDesc());
		}
		Result result  = new Result();
		Map resultMap = orderQuery(orderNo);//查询操作
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		String result_code = resultMap.get("result_code").toString();
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
					result.setData(resultMap);
				}else if(trade_state.toString().equals("USERPAYING")){
				
					result = handelQueryResult(orderNo,flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	/**
	 * 处理支付结果服务商
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年1月18日 下午6:09:53 <br/>
	 */
	private Result handelQueryResultForService(String orderNo,String flag,long times) throws Exception{
		Thread.sleep(5000);
		times = times + 5000;
		if(times >= 30000){
			throw new BusinessException(WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getCode()
					,WxPayForScanReturnCodeEnum.PAY_OUTTIME_FAILURE.getDesc());
		}
		Result result  = new Result();
		Map resultMap = orderQueryForService(orderNo);
		String retrun_code = resultMap.get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		if(retrun_code.equals("SUCCESS")){
			String result_code = resultMap.get("result_code").toString();
			Object err_code_des = resultMap.get("err_code_des");
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
					result.setData(resultMap);
				}else if(trade_state.toString().equals("USERPAYING")){
					result = handelQueryResultForService(orderNo,flag,times);
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
	}
	
	/**
	 * 微信刷卡扫码支付查询
	 * 功能: <br/>
	 * 
	 * 重写：sunyl <br/>
	 * 
	 * @Date ：2018年1月18日 上午10:46:54<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.guest.service.WxPayService#orderQuery(java.lang.String)
	 */
	@Override
	public Map orderQuery(String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid",appid );
        data.put("mch_id",mch_id );
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
        
        RequestHandler reqHandler = new RequestHandler(null, null);
        reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), 
        		ConfigUtil.get(WxConstant.APP_SECRET), 
        		ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/pay/orderquery";
		 String xml  = "<xml>"
		   +"<appid>"+appid+"</appid>"
		   +"<mch_id>"+mch_id+"</mch_id>"
		   +"<nonce_str>"+nonce_str+"</nonce_str>"
		   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
		   +"<sign>"+sign+"</sign>"
		+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 服务商查询
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月6日 上午11:41:37<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.guest.service.WxPayService#orderQueryForService(java.lang.String)
	 */
	@Override
	public Map orderQueryForService(String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		/*String mch_id = ConfigUtil.get(WxConstant.MCH_ID);*/
		String mch_id = "1497953662";
		String sub_mch_id = "1498287672";
		String nonce_str = getNonceStr();
		data.put("appid",appid );
		data.put("mch_id",mch_id );
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("sub_mch_id", sub_mch_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), 
				ConfigUtil.get(WxConstant.APP_SECRET), 
				ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/pay/orderquery";
		String xml  = "<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 撤销
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月6日 上午11:41:49<br/>
	 * 
	 * @param out_trade_no
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.guest.service.WxPayService#reverse(java.lang.String)
	 */
	@Override
	public Map reverse(String out_trade_no) throws Exception{
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
		data.put("appid",appid );
		data.put("mch_id",mch_id );
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), 
				ConfigUtil.get(WxConstant.APP_SECRET), 
				ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
		String xml  = "<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		return GetWxOrderno.getHttpMap(url, xml);
	}
	/**
	 * 撤銷訂單
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月5日 上午10:33:19<br/>
	 * 
	 * @param money
	 * @param out_trade_no
	 * @param auth_code
	 * @param spbill_create_ip
	 * @param flag  本來是爲了區分預訂單和訂單額區別，沒用了
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.guest.service.WxPayService#reverse(java.math.BigDecimal, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result reverse(BigDecimal money, String out_trade_no, String auth_code, String spbill_create_ip, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
        data.put("appid", appid);
        data.put("auth_code", auth_code);
        data.put("body", "门店扫码");
        data.put("mch_id",mch_id);
        data.put("nonce_str", nonce_str);
        data.put("out_trade_no", out_trade_no);
		String totalFee = getMoney(money.toString());
		// 这里写的金额为1 分到时修改
		data.put("spbill_create_ip", spbill_create_ip);
        data.put("total_fee", totalFee);// totalFee
        
        RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		
		data.put("sign", sign);
		 String url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
		 String xml = "<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		 
		 Result result  = new Result();
		 Map resultMap  = GetWxOrderno.getHttpMap(url, xml);
			String retrun_code = resultMap .get("return_code").toString();
			Object return_msg = resultMap.get("return_msg");
			String result_code = resultMap.get("result_code").toString();
			Object err_code_des = resultMap.get("err_code_des");
			String recall = resultMap.get("recall").toString();
			if(retrun_code.equals("SUCCESS")){
				if(result_code.equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_SUCCESS.getDesc());
				}else{
					if(recall.equals("Y")){
						return this.reverse(money, out_trade_no, auth_code, spbill_create_ip, flag);
					}else{
						result.setStatus(ReturnStatusEnum.FAILURE.getCode());
						result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
						result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
						result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
						result.setData(err_code_des);
					}
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.RESERVE_FAILURE.getDesc());
				result.setData(return_msg);
			}
			return result;
		 
	}
	/**
	 * 撤銷訂單
	 * 功能: <br/>
	 * 
	 * 重写：xuehj <br/>
	 * 
	 * @Date ：2018年2月5日 上午10:33:19<br/>
	 * 
	 * @param money
	 * @param out_trade_no
	 * @param auth_code
	 * @param spbill_create_ip
	 * @param flag  本來是爲了區分預訂單和訂單額區別，沒用了
	 * @return
	 * @throws Exception <br/>
	 * @see com.yuju.guest.service.WxPayService#reverse(java.math.BigDecimal, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public Result refund(BigDecimal refund_fee,BigDecimal total_fee, String out_trade_no, String transaction_id, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String appid = ConfigUtil.get(WxConstant.APP_ID);
		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);
		String nonce_str = getNonceStr();
		data.put("appid", appid);
		data.put("mch_id",mch_id);
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("out_refund_no", out_trade_no);
		String totalFee = getMoney(total_fee.toString());
		String refundFee = getMoney(refund_fee.toString());
		// 这里写的金额为1 分到时修改
		data.put("refund_fee", refundFee);// totalFee
		data.put("total_fee", totalFee);// totalFee
		data.put("transaction_id", transaction_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		String xml ="<xml>"
					   +"<appid>"+appid+"</appid>"
					   +"<mch_id>"+mch_id+"</mch_id>"
					   +"<nonce_str>"+nonce_str+"</nonce_str>" 
					   +"<out_refund_no>"+out_trade_no+"</out_refund_no>"
					   +"<out_trade_no>"+out_trade_no+"</out_trade_no>"
					   +"<refund_fee>"+refundFee+"</refund_fee>"
					   +"<total_fee>"+totalFee+"</total_fee>"
					   +"<transaction_id>"+transaction_id+"</transaction_id>"
					   +"<sign>"+sign+"</sign>"
					+"</xml>";
		System.out.println("请求的url:"+url+"xml:"+xml);
		KeyStore keyStore  = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
		Result result  = new Result();
		Map resultMap  = GetWxOrderno.getRefund(url, instream, xml, mch_id);
		String retrun_code = resultMap .get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code_des = resultMap.get("err_code_des");
		Object recall = resultMap.get("recall");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getDesc());
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
		
	}
	@Override
	public Result refundForService(String groupId,BigDecimal refund_fee,BigDecimal total_fee, String out_trade_no, String transaction_id, String flag)
			throws Exception {
		SortedMap<String, String> data = new TreeMap<String, String>();
		String mch_id = cache.get(groupId + Constant.MCH_ID + CacheKey.KEY_GRP_PARAM);
		String appid = cache.get(groupId + Constant.APP_ID + CacheKey.KEY_GRP_PARAM);
		//String appid = ConfigUtil.get(WxConstant.APP_ID);
		//String appid = cache.get(Constant.MCH_ID);
		/*		String mch_id = ConfigUtil.get(WxConstant.MCH_ID);*/
		//String mch_id = "1497953662";
		String sub_mch_id = "1498287672";
		//String sub_mch_id = cache.get(groupId + Constant.S + CacheKey.KEY_GRP_PARAM);
		String nonce_str = getNonceStr();
		data.put("appid", appid);
		data.put("mch_id",mch_id);
		data.put("nonce_str", nonce_str);
		data.put("out_trade_no", out_trade_no);
		data.put("out_refund_no", out_trade_no);
		String totalFee = getMoney(total_fee.toString());
		String refundFee = getMoney(refund_fee.toString());
		// 这里写的金额为1 分到时修改
		data.put("refund_fee", refundFee);// totalFee
		data.put("sub_mch_id", sub_mch_id);
		data.put("total_fee", totalFee);// totalFee
		data.put("transaction_id", transaction_id);
		
		RequestHandler reqHandler = new RequestHandler(null, null);
		reqHandler.init(ConfigUtil.get(WxConstant.APP_ID), ConfigUtil.get(WxConstant.APP_SECRET), ConfigUtil.get(WxConstant.MCH_KEY));
		String sign = reqHandler.createSign(data);
		data.put("sign", sign);
		String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		String xml ="<xml>"
				+"<appid>"+appid+"</appid>"
				+"<mch_id>"+mch_id+"</mch_id>"
				+"<nonce_str>"+nonce_str+"</nonce_str>" 
				+"<sub_mch_id>"+sub_mch_id+"</sub_mch_id>"
				+"<out_refund_no>"+out_trade_no+"</out_refund_no>"
				+"<out_trade_no>"+out_trade_no+"</out_trade_no>"
				+"<refund_fee>"+refundFee+"</refund_fee>"
				+"<total_fee>"+totalFee+"</total_fee>"
				+"<transaction_id>"+transaction_id+"</transaction_id>"
				+"<sign>"+sign+"</sign>"
				+"</xml>";
		System.out.println("请求的url:"+url+"xml:"+xml);
		KeyStore keyStore  = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
		Result result  = new Result();
		Map resultMap  = GetWxOrderno.getRefund(url, instream, xml, mch_id);
		String retrun_code = resultMap .get("return_code").toString();
		Object return_msg = resultMap.get("return_msg");
		Object result_code = resultMap.get("result_code");
		Object err_code_des = resultMap.get("err_code_des");
		Object recall = resultMap.get("recall");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_SUCCESS.getDesc());
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.REFUND_FAILURE.getDesc());
			result.setData(return_msg);
		}
		return result;
		
	}
	private void certificate() throws NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, UnrecoverableKeyException, KeyStoreException{
		 KeyStore keyStore  = KeyStore.getInstance("PKCS12");
	        FileInputStream instream = new FileInputStream(new File("F:/cert/apiclient_cert.p12"));
	        try {
	            keyStore.load(instream, "1497953662".toCharArray());
	        } finally {
	            instream.close();
	        }

	        // Trust own CA and all self-signed certs
	        SSLContext sslcontext = SSLContexts.custom()
	                .loadKeyMaterial(keyStore, "1497953662".toCharArray())
	                .build();
	        // Allow TLSv1 protocol only
	        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
	                sslcontext,
	                new String[] { "TLSv1" },
	                null,
	                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
	        CloseableHttpClient httpclient = HttpClients.custom()
	                .setSSLSocketFactory(sslsf)
	                .build();
	}
}
